﻿#include "phasewidget.h"
#include <QtMath>
#include <QDebug>

#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif


PhaseWidget::PhaseWidget(QWidget* parent) :
    QWidget(parent),
    m_phase(0.0),
    m_targetPhase(0.0),
    m_editable(true),
    m_animated(true),
    m_animationDuration(500),
    m_animationTimer(new QTimer(this)),
    m_animationProgress(0),
    m_isDragging(false),
    m_minPhase(0.0),
    m_maxPhase(360.0),
    m_radialGridCount(4),    // 12条径向网格线(每30度一条)
    m_circularGridCount(5),   // 5条圆形网格线
    m_showAngleLabels(true),
    m_showPhaseValue(true),
    m_referenceValue(1.0),
    m_showOverrange(false),
    m_showGrid(false),
    m_backColor("#050d2c"),
    m_foregroundColor("#FFFFFF"),
    m_font("Arial", 12)
{
    setFont(m_font);
    setMinimumSize(30, 30);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    connect(m_animationTimer, &QTimer::timeout, this, &PhaseWidget::onAnimationTimerTimeout);
}

PhaseWidget::~PhaseWidget()
{
}

// 获参考取值
double PhaseWidget::referenceValue() const
{
    return m_referenceValue;
}
// 设置参考值
void PhaseWidget::setReferenceValue(double value)
{
    if (qFuzzyCompare(m_referenceValue, value)) {
        return;
    }
    m_referenceValue = value;
    update();
    // 看哪里需要专注这个变化
    emit referenceValueChanged(m_referenceValue);
}

double PhaseWidget::phase() const
{
    return m_phase;
}

void PhaseWidget::setPhase(double phase)
{
    // 限制相位在指定范围内
    phase = qBound(m_minPhase, phase, m_maxPhase);
    phase = normalizePhase(phase);

    if (qFuzzyCompare(m_phase, phase))
        return;

    m_phase = phase;
    update();
    emit phaseChanged(m_phase);
}

void PhaseWidget::setPhaseAnimated(double targetPhase)
{
    // 限制相位在指定范围内
    targetPhase = qBound(m_minPhase, targetPhase, m_maxPhase);
    targetPhase = normalizePhase(targetPhase);

    if (qFuzzyCompare(m_phase, targetPhase))
        return;

    m_targetPhase = targetPhase;
    m_animationProgress = 0;

    if (m_animated) {
        if (!m_animationTimer->isActive())
            m_animationTimer->start(16); // 约60FPS
    } else {
        setPhase(targetPhase);
    }
}

bool PhaseWidget::editable() const
{
    return m_editable;
}

void PhaseWidget::setEditable(bool editable)
{
    if (m_editable == editable)
        return;

    m_editable = editable;
    setCursor(m_editable ? Qt::CrossCursor : Qt::ArrowCursor);
    emit editableChanged(m_editable);
}

bool PhaseWidget::animated() const
{
    return m_animated;
}

void PhaseWidget::setAnimated(bool animated)
{
    if (m_animated == animated)
        return;

    m_animated = animated;
    emit animatedChanged(m_animated);
}

int PhaseWidget::animationDuration() const
{
    return m_animationDuration;
}

void PhaseWidget::setAnimationDuration(int duration)
{
    if (m_animationDuration == duration)
        return;

    m_animationDuration = duration;
    emit animationDurationChanged(m_animationDuration);
}

void PhaseWidget::setPhaseRange(double minPhase, double maxPhase)
{
    m_minPhase = qMin(minPhase, maxPhase);
    m_maxPhase = qMax(minPhase, maxPhase);
    setPhase(m_phase); // 重新应用范围限制
}

QPair<double, double> PhaseWidget::phaseRange() const
{
    return qMakePair(m_minPhase, m_maxPhase);
}

void PhaseWidget::setGridCount(int radialCount, int circularCount)
{
    m_radialGridCount = qMax(1, radialCount);
    m_circularGridCount = qMax(1, circularCount);
    update();
}

void PhaseWidget::setShowAngleLabels(bool show)
{
    if (m_showAngleLabels == show)
        return;

    m_showAngleLabels = show;
    update();
}

void PhaseWidget::setShowPhaseValue(bool show)
{
    if (m_showPhaseValue == show)
        return;

    m_showPhaseValue = show;
    update();
}

// 设置超量程
void PhaseWidget::setShowOverrange(bool show)
{
    if (m_showOverrange == show) {
        return;
    }

    m_showOverrange = show;
    update();
}

// 设置网格显示
void PhaseWidget::setShowGrid(bool show)
{
    if (m_showGrid == show) {
        return;
    }

    m_showGrid = show;
    update();
}

void PhaseWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    // 绘制背景
    // painter.fillRect(rect(), QColor(6, 12, 44));
    // painter.fillRect(rect(), m_backColor);

    // 绘制相位名称和活动事件
    drawPaseInfo(painter);

    // 绘制极坐标背景
    drawPolarBackground(painter);

    // 绘制相位指针
    drawPhaseIndicator(painter);

    // 绘制角度标签
    if (m_showAngleLabels)
        drawAngleLabels(painter);

    // 绘制相位值文本
    if (m_showPhaseValue)
        drawPhaseValue(painter);
}

void PhaseWidget::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event);
    update();
}

void PhaseWidget::mousePressEvent(QMouseEvent *event)
{
    if (!m_editable || event->button() != Qt::LeftButton) {
        QWidget::mousePressEvent(event);
        return;
    }

    m_isDragging = true;
    m_lastMousePos = event->pos();

    // 计算鼠标点击位置对应的相位
    double angle = pointToAngle(event->pos());
    setPhase(angle);

    emit userInteractionStarted();
    event->accept();
}

void PhaseWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (!m_editable || !m_isDragging) {
        QWidget::mouseMoveEvent(event);
        return;
    }

    // 计算鼠标移动对应的相位变化
    double angle = pointToAngle(event->pos());
    setPhase(angle);

    m_lastMousePos = event->pos();
    event->accept();
}

void PhaseWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (!m_editable || event->button() != Qt::LeftButton || !m_isDragging) {
        QWidget::mouseReleaseEvent(event);
        return;
    }

    m_isDragging = false;
    emit userInteractionFinished();
    event->accept();
}

void PhaseWidget::wheelEvent(QWheelEvent *event)
{
    if (!m_editable) {
        QWidget::wheelEvent(event);
        return;
    }

    // 根据鼠标滚轮调整相位
    double delta = event->angleDelta().y() / 8.0; // 转换为角度
    double step = qAbs(delta) > 10 ? 10.0 : 1.0;  // 大滚动使用大步长，小滚动使用小步长
    step *= (delta > 0 ? 1.0 : -1.0);

    setPhase(m_phase + step);
    event->accept();
}

/// <summary>
/// 绘制极坐标背景
/// </summary>
/// <param name="painter"></param>
void PhaseWidget::drawPolarBackground(QPainter &painter)
{
    // 计算中心点和半径
    int centerX1 = width() / 2;
    int centerY1 = height() / 2;
    bool bFlagWight = centerX1 < centerY1 ? true : false;  // 是否宽<高
    int radius1 = qMin(width(), height()) / 2 - 20;
    QPen pen1("#FF0000");

    QRect rectWidget = geometry();
    QRect rectEllipse = QRect(centerX1 - radius1, centerY1 - radius1, radius1 * 2, radius1 * 2);

    //if(m_rectText.width())

    QPoint pinter = m_rectText.bottomRight();

    if (isInsideTopElipse(rectEllipse, pinter)) { // 矩形有相交
                qDebug() << "矩形有相交";
    } else {
        if (pinter.x() > rectEllipse.left() + rectEllipse.width() * 0.5) {
            rectWidget.adjust(m_rectText.bottomRight().x(), 0, 0, 0);
        }
        else if (pinter.y() > rectEllipse.top() + rectEllipse.height() * 0.5) {
            rectWidget.adjust(m_rectText.bottomRight().y(), 0, 0, 0);
        }
        else {
            // 如果数据超标了，这个地方需要修改
            int  x = m_rectText.bottom();
            int x1 = m_rectPhase.top();
            int y = m_rectText.right();
            int y1 = m_rectPhase.left();

            if (m_rectText.bottom() < m_rectPhase.top()) {
                rectWidget.adjust(0, m_rectText.top(), 0, 0);
            }
            else if (m_rectText.right() < m_rectPhase.left()) {
                rectWidget.adjust(m_rectText.left(), 0, 0, 0);
            }
            /*else {
                rectWidget.adjust(m_rectText.right(), 0, 0, 0);
            }*/ else {
                int rightBoundary = rectEllipse.left() + rectEllipse.width() * 0.15;
                int bottomBoundary = rectEllipse.top() + rectEllipse.height() * 0.15;

                bool a = pinter.x() >= rectEllipse.left() && pinter.x() <= rightBoundary;
                if (!a) {

                }
                bool b = pinter.y() >= rectEllipse.top() && pinter.y() <= bottomBoundary;
                if (!b) {

                }
            }
            

            
            painter.drawRect(rectWidget);
        }
    }

    painter.drawRect(rectWidget);
    // 计算中心点和半径
    int centerX = rectWidget.x() +  rectWidget.width() / 2;
    int centerY = rectWidget.y() + rectWidget.height() / 2;
   // bool bFlagWight = centerX < centerY ? true : false;  // 是否宽<高
    int radius = qMin(rectWidget.width(), rectWidget.height()) / 2 - 20;
    m_rectPhase = QRect(centerX - radius, centerY - radius, radius * 2, radius * 2);
    painter.save();
    painter.setPen(pen1);
    painter.drawRect(m_rectPhase);
    painter.restore();

    painter.save();
    QPen pen(m_foregroundColor, 1);
    if (m_showOverrange) {
        pen.setStyle(Qt::DashLine);
        painter.setPen(pen);
        painter.drawEllipse(QPointF(centerX, centerY), radius, radius);
        pen.setStyle(Qt::SolidLine);
        painter.setPen(pen); 
        int realRadius = radius * 0.8;
        if (m_showGrid) {
            painter.save();
            pen.setStyle(Qt::DashLine);
            painter.setPen(pen);
            painter.drawEllipse(QPointF(centerX, centerY), realRadius * 0.5, realRadius * 0.5);
            painter.restore();
        } 
        painter.drawEllipse(QPointF(centerX, centerY), realRadius, realRadius);
    } else {
        // 设置网格画笔
        painter.setPen(pen);
        painter.drawEllipse(QPointF(centerX, centerY), radius, radius);
    }
    // 绘制径向网格线和角度标签位置标记
    for (int i = 0; i < m_radialGridCount; ++i) {
        painter.setPen(pen);
        double angle = i * 360.0 / m_radialGridCount;
        QPointF outerPoint = angleToPoint(angle, 1.0);
        // QPointF innerPoint = angleToPoint(angle, 0.95); // 稍微短一点以留出标签空间

        painter.drawLine(QPointF(centerX, centerY), outerPoint);

        if (angle == 90) {
            // 如果时90，绘制%100
            QPointF labelPos;
            m_showOverrange == true ? labelPos = angleToPoint(90, 0.75) : labelPos = angleToPoint(90, 0.95);
            labelPos.setY(labelPos.y() + 5);
            // 绘制角度标签
            painter.drawText(labelPos, "100%");
        }
    }

    if (m_showGrid) {
        for (int i = 0; i < 12; i++) {
            if (i % 3 == 0) {
                continue;
            }
            double angle = i * 360.0 / 12;
            QPointF outerPoint = angleToPoint(angle, 1.0);
            // QPointF innerPoint = angleToPoint(angle, 0.95); // 稍微短一点以留出标签空间
            QPen pen(m_foregroundColor);
            pen.setWidth(1);
            pen.setStyle(Qt::DashLine);
            painter.setPen(pen);
            painter.drawLine(QPointF(centerX, centerY), outerPoint);

        }
    } 
    

    // 绘制中心圆, 取消绘制中心圆
    /*painter.setBrush(QColor(255, 255, 255));
   // painter.drawEllipse(QPointF(centerX, centerY), 5, 5);*/

    // 恢复画家状态
    painter.restore();
}

 // 绘制相位指针
void PhaseWidget::drawPhaseIndicator(QPainter &painter)
{
    // 计算中心点和半径
    int centerX = width() / 2;
    int centerY = height() / 2;
    int radius = qMin(width(), height()) / 2 - 20;

    // 保存当前画家状态
    painter.save();

    // 设置指针画笔和画刷
    QPen indicatorPen(QColor(255, 69, 0)); // 橙红色
    indicatorPen.setWidth(2);
    painter.setPen(indicatorPen);
    painter.setBrush(QColor(255, 69, 0));

    // 计算指针终点位置
    QPointF pointerEnd = angleToPoint(m_phase, m_referenceValue); // 指针长度为半径的85%
    
    // 增加一个节点作为计算箭头使用
    QPointF pointerArrow = angleToPoint(m_phase, m_referenceValue * 0.95); // 指针长度为半径的85%

    // 绘制指针线
    painter.drawLine(QPointF(centerX, centerY), pointerEnd);

    double arrowAngle1 = m_phase + 3; // 箭头两侧的角度
    double arrowAngle2 = m_phase - 3;

    QPointF arrowPoint1 = angleToPoint(arrowAngle1, m_referenceValue * 0.9);
    QPointF arrowPoint2 = angleToPoint(arrowAngle2, m_referenceValue * 0.9);

    QPolygonF arrow;
    arrow << pointerEnd << arrowPoint1 << pointerArrow << arrowPoint2 << pointerEnd;
    painter.drawPolygon(arrow);

    // 绘制指针尾部(小圆点)
    // painter.setBrush(QColor(255, 255, 255));
    // 取消中心点的绘制
    // painter.drawEllipse(QPointF(centerX, centerY), 3, 3);

    // 恢复画家状态
    painter.restore();
}

/// <summary>
/// 绘制角度
/// </summary>
/// <param name="painter"></param>
void PhaseWidget::drawAngleLabels(QPainter &painter)
{
    // 计算中心点和半径
    int centerX = width() / 2;
    int centerY = height() / 2;
    int radius = qMin(width(), height()) / 2 - 20;

    // 保存当前画家状态
    painter.save();

    // 设置标签字体
    QFont labelFont = font();
    labelFont.setPointSizeF(labelFont.pointSizeF() * 0.8);
    painter.setFont(labelFont);

    // 绘制角度标签
    int drawAngle = 90;
    m_showGrid == true ? drawAngle = 30 : drawAngle = 90;
    for (int i = 0; i < 360; i += drawAngle) {
        double angle = i;
        QPointF labelPos = angleToPoint(angle, 1.07); // 标签位置稍微向外

        // 调整标签位置，避免重叠
        if (angle >= 315 || angle <= 45)
            labelPos.setX(labelPos.x() + 5);
        else if (angle >= 135 && angle <= 225)
            labelPos.setX(labelPos.x() - 15);

        if (angle >= 45 && angle <= 135)
            labelPos.setY(labelPos.y() + 5);
        else if (angle >= 225 && angle <= 315)
            labelPos.setY(labelPos.y() - 10);

        // 绘制角度标签
        QPen pen(m_foregroundColor, 1);
        painter.setPen(pen);
        painter.drawText(labelPos, QString::number(i) + "°");
    }

    // 恢复画家状态
    painter.restore();
}

void PhaseWidget::drawPhaseValue(QPainter &painter)
{
    // 计算中心点
    int centerX = width() / 2;
    int centerY = height() / 2;

    // 保存当前画家状态
    painter.save();

    // 设置文本字体和颜色
    QFont textFont = font();
    textFont.setBold(true);
    textFont.setPointSizeF(textFont.pointSizeF() * 1.2);
    painter.setFont(textFont);
    painter.setPen(QColor(50, 50, 50));

    // 格式化相位值文本
    QString phaseText = QString("相位: %1°").arg(QString::number(m_phase, 'f', 1));

    // 绘制文本背景

    QRectF textRect(centerX - 70, centerY - 15, 140, 30);
    painter.fillRect(textRect, QColor(255, 255, 255, 180));
    painter.drawRect(textRect);

    // 绘制文本
    painter.drawText(textRect, Qt::AlignCenter, phaseText);

    // 恢复画家状态
    painter.restore();
}

QPointF PhaseWidget::angleToPoint(double angle, double radiusFactor) const
{
    // 计算中心点和半径
    double centerX = width() / 2.0;
    double centerY = height() / 2.0;
    double radius = qMin(width(), height()) / 2.0 - 20.0;

    // 将角度转换为弧度(注意Qt坐标系中y轴向下，所以角度需要取负)
    double rad = qDegreesToRadians(-angle); // 0度在顶部

    // 计算坐标
    double x = centerX + radius * radiusFactor * std::cos(rad);
    double y = centerY + radius * radiusFactor * std::sin(rad);

    return QPointF(x, y);
}

double PhaseWidget::pointToAngle(const QPointF &point) const
{
    // 计算中心点
    double centerX = width() / 2.0;
    double centerY = height() / 2.0;

    // 计算相对于中心点的坐标
    double dx = point.x() - centerX;
    double dy = point.y() - centerY;

    // 计算角度(atan2返回的是弧度，转换为角度)
    double angle = qRadiansToDegrees(std::atan2(dy, dx));

    // 将角度转换为0-360度范围
    angle =  -angle; // 调整坐标系，使0度在顶部
    if (angle < 0)
        angle += 360;

    return angle;
}

double PhaseWidget::normalizePhase(double phase) const
{
    while (phase < 0)
        phase += 360;
    while (phase >= 360)
        phase -= 360;
    return phase;
}

void PhaseWidget::updateAnimation()
{
    if (m_animationProgress >= 100) {
        m_animationTimer->stop();
        setPhase(m_targetPhase);
        return;
    }

    // 使用缓动函数使动画更自然
    double progress = m_animationProgress / 100.0;
    double easeProgress = 0.5 * (1 - std::cos(progress * M_PI)); // 余弦缓动函数

    // 计算当前插值相位
    double currentPhase = m_phase + (m_targetPhase - m_phase) * easeProgress;
    setPhase(currentPhase);

    // 更新动画进度
    m_animationProgress += qMax(1, static_cast<int>(100 * 16 / static_cast<double>(m_animationDuration)));
}

void PhaseWidget::onAnimationTimerTimeout()
{
    updateAnimation();
}

/// <summary>
///  计算矩形区域
/// </summary>
void PhaseWidget::calculateRectRage()
{
    //QStringList listLines;
    //// 找出最长行
    //for (const auto& group : m_listGroupInfo) {
    //    if (!group->groupName.isEmpty()) {
    //        listLines << group->groupName;
    //    }
    //    for (const auto& channal : group->listChannel) {
    //        listLines << QString("%1  %2  %3").arg(channal->channelname).arg(channal->phaseSize).arg(channal->value);
    //    }
    //}

    //QPainter painter(this);
    //QFontMetrics fm(m_font);

    //int maxWidth = 0;
    //int linHeight = fm.height();
    //int totalHeight = linHeight * listLines.size();

    //for (const QString& line : listLines) {
    //    int lineWidth = fm.horizontalAdvance(line);
    //    maxWidth = qMax(maxWidth, lineWidth);
    //}

    //m_rectText = QRect(8, 8, maxWidth, totalHeight);


}


/// <summary>
/// 绘制相位名称和相位值，右上角部分
/// </summary>
/// <param name="painter"></param>
void PhaseWidget::drawPaseInfo(QPainter& painter)
{
    // 保存当前画家状态
    int startXPos = 8;
    int startYPos = 8;
    QString strTest = "ADFASDaaaaaaFADSF";
    painter.save();

    QFontMetrics fm(m_font);
    int textWidth = fm.horizontalAdvance(strTest);
    // 绘制圆角矩形
    painter.setBrush(Qt::NoBrush); // 设置填充颜色
    painter.setPen(m_foregroundColor);    // 设置边框颜色
    m_rectText = QRect(startXPos, startXPos, textWidth, 20 * 5);
    painter.drawRect(m_rectText);

    // 绘制文字（居中）
    painter.drawText(QRect(startXPos, startYPos, textWidth, 20), Qt::AlignLeft, strTest);

    painter.restore();
}


/// <summary>
/// 计算文本的矩形是否在矩形的左上0.3倍
/// </summary>
/// <param name="rect"></param>
/// <param name="point"></param>
bool PhaseWidget::isInsideTopElipse(const QRect& rect, const QPoint& point)
{
    // 计算左上角五分之一区域的右边界和下边界
    int rightBoundary = rect.left() + rect.width() * 0.15;
    int bottomBoundary = rect.top() + rect.height() * 0.15;

    bool a = point.x() >= rect.left() && point.x() <= rightBoundary;
    bool b = point.y() >= rect.top() && point.y() <= bottomBoundary;

    // 判断点是否在这个范围内
    return  a && b;
        
}